package com.cosmosource.core.advice;


import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 全局响应体增强.
 *
 * @author JC.
 */
@ControllerAdvice(basePackages = "com.cosmosource.controller")
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }


    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<?
            extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        if (excludeFilter(returnType) || body instanceof ResponsePagedEntity) {
            return body;
        }
        // 会提示有问题，但是不加还不好使。懂得大佬可以改下。也可能是我自己的代码有问题
        if (body instanceof ResponseEntity) {
            return body;
        }
        return ResponseEntity.success("请求成功", body);
    }

    /**
     * 需要放行则返回true否则返回false
     *
     * @param returnType 接口参数
     * @return true:放行，false:正常通过
     */
    private Boolean excludeFilter(MethodParameter returnType) {
        List<List<Annotation>> annotations = new ArrayList<>();
        annotations.add(Arrays.asList(returnType.getMethodAnnotations()));
        annotations.add(Arrays.asList(returnType.getDeclaringClass().getDeclaredAnnotations()));
        return annotations.stream()
                .flatMap(Collection::stream)
                .anyMatch(q -> q.annotationType() == ExcludeResponseBodyAdviceAnnotation.class);
    }
}
